<!doctype html>
<html lang="en" class="page-type-section">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>基本内容 - FreeMarker 手册</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="format-detection" content="telephone=no">
<meta property="og:site_name" content="FreeMarker 手册">
<meta property="og:title" content="基本内容">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="http://freemarker.org/docs/xgui_imperative_learn.html">
<link rel="canoical" href="http://freemarker.org/docs/xgui_imperative_learn.html">
<link rel="icon" href="favicon.png" type="image/png">
<link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css">
</head>
<body itemscope itemtype="https://schema.org/Code">
    <meta itemprop="url" content="http://freemarker.org/docs/">
    <meta itemprop="name" content="FreeMarker 手册">

  <!--[if lte IE 9]>
  <div style="background-color: #C00; color: #fff; padding: 12px 24px;">Please use a modern browser to view this website.</div>
  <![endif]--><div class="header-top-bg"><div class="site-width header-top"><a class="logo" href="http://freemarker.org" role="banner">            <img itemprop="image" src="logo.png" alt="FreeMarker">
</a><ul class="tabs"><li><a href="http://freemarker.org/">Home</a></li><li class="current"><a href="index.html">Manual</a></li><li><a class="external" href="http://freemarker.org/docs/api/index.html">Java API</a></li></ul><ul class="secondary-tabs"><li><a class="tab icon-heart" href="http://freemarker.org/contribute.html" title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug" href="https://sourceforge.net/p/freemarker/bugs/new/" title="Report a Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download" href="http://freemarker.org/freemarkerdownload.html" title="Download"><span>Download</span></a></li></ul></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="toc.html" class="navigation-header">Manual</a><div class="navigation-header"></div></div><div class="site-width breadcrumb-row"><ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="toc.html"><span itemprop="name">FreeMarker 手册</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="xgui.html"><span itemprop="name">XML处理指南</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="xgui_imperative.html"><span itemprop="name">必要的XML处理</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="xgui_imperative_learn.html"><span itemprop="name">基本内容</span></a></li></ul><div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul class="bookmark-list"><li><a href="alphaidx.html">Alpha. index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions</a></li><li><a href="ref_builtins_alphaidx.html">?builtins</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_specvar.html">.spec_vars</a></li><li><a href="app_faq.html">FAQ</a></li></ul></div></div></div>    <div class="main-content site-width">
      <div class="content-wrapper">
  <div id="table-of-contents-wrapper" class="col-left">
      <script>var breadcrumb = ["FreeMarker 手册","XML处理指南","必要的XML处理","基本内容"];</script>
      <script src="toc.js"></script>
      <script src="docgen-resources/main.min.js"></script>
  </div>
<div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="xgui_imperative.html"><span>Previous</span></a><a class="paging-arrow next" href="xgui_imperative_formal.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="xgui_imperative_learn" itemprop="headline">基本内容</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_132" data-menu-target="autoid_132">通过名称来访问元素</a></li><li><a class="page-menu-link" href="#autoid_133" data-menu-target="autoid_133">访问属性</a></li><li><a class="page-menu-link" href="#autoid_134" data-menu-target="autoid_134">探索DOM树</a></li><li><a class="page-menu-link" href="#autoid_135" data-menu-target="autoid_135">使用XPath表达式</a></li><li><a class="page-menu-link" href="#autoid_136" data-menu-target="autoid_136">XML命名空间</a></li><li><a class="page-menu-link" href="#autoid_137" data-menu-target="autoid_137">不要忘了转义！</a></li></ul> </div>  <div class="callout note">
    <strong class="callout-label">Note:</strong>

          <p>这部分我们使用的DOM树和变量都是<a href="xgui_expose.html">前一章</a>做的那个。</p>
          </div>
<p>假设程序员在数据模型中放置了一个XML文档，就是名为 
		<code class="inline-code">doc</code> 的变量。这个变量和<a href="xgui_expose_dom.html">DOM 树</a>的根结点&quot;document&quot;对应。
		真实的变量 <code class="inline-code">doc</code> 之后结构是非常复杂的，
		大约类似DOM树。所以为了避免钻牛角尖，我们通过例子来看看如何使用。</p>
          



<h2 class="content-header header-section2" id="autoid_132">通过名称来访问元素</h2>


          <p>这个FTL打印book的title：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;h1&gt;${doc.book.title}&lt;/h1&gt;</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">&lt;h1&gt;Test Book&lt;/h1&gt;</pre></div>

          <p>正如你所看到的，<code class="inline-code">doc</code> 和 <code class="inline-code">book</code> 
		  都可以当作哈希表来使用。你可以按照子变量的形式来获得它们的子结点。
		  基本上，你用描述路径的方法来访问在DOM树中的目标(元素<code class="inline-code">title</code>)。
		  你也许注意到了上面有一些是假象:使用 <code class="inline-code">${doc.book.title}</code>，
		  就好像我们指示 FreeMarker 打印 <code class="inline-code">title</code> 元素本身，
		  但是我们应该打印它的子元素文本(看看 <a href="xgui_expose_dom.html">DOM 树</a>)。
		  那也可以办到，因为元素不仅仅是哈希表变量，也是字符串变量。
		  元素结点的标量是从它的文本子结点级联中获取的字符串结果。然而，如果元素有子元素，
		  尝试使用一个元素作为标量会引起错误。比如<code class="inline-code">${doc.book}</code>将会以错误而终止。</p>

          <p>该FTL打印2个chapter的title：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;h2&gt;${doc.book.chapter[0].title}&lt;/h2&gt;
&lt;h2&gt;${doc.book.chapter[1].title}&lt;/h2&gt;</pre></div>

          <p>这里，<code class="inline-code">book</code> 有两个 <code class="inline-code">chapter</code> 子元素，
		  <code class="inline-code">doc.book.chapter</code> 是存储两个元素结点的序列。
		  因此，我们可以概括上面的FTL，所以它以任意chapter的数量起作用：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#list doc.book.chapter as ch&gt;
  &lt;h2&gt;${ch.title}&lt;/h2&gt;
&lt;/#list&gt;</pre></div>

          <p>但是如果只有一个chapter会怎么样呢？实际上，
		  当你访问一个作为哈希表子变量的元素时，<em>通常</em> 
		  也可以是序列(不仅仅是哈希表和字符串)，但如果序列只包含一个项，
		  那么变量也作为项目自身。所以，回到第一个示例中，它也会打印book的title：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;h1&gt;${doc.book[0].title[0]}&lt;/h1&gt;</pre></div>

          <p>但是你知道那里就只有一个 <code class="inline-code">book</code> 元素，
		  而且book也就只有一个title，所以你可以忽略那些 <code class="inline-code">[0]</code>。
		  如果book恰好有一个 <code class="inline-code">chapter</code>(否则它就是模糊的：
		  它怎么知道你想要的是哪个 <code class="inline-code">chapter</code> 的 <code class="inline-code">title</code>？
		  所以它就会以错误而停止)，<code class="inline-code">${doc.book.chapter.title}</code> 也可以正常进行。
		  但是因为一个book可以有很多chapter，你不能使用这种形式。如果元素 
		  <code class="inline-code">book</code> 没有子元素 <code class="inline-code">chapter</code>，
		  那么 <code class="inline-code">doc.book.chapter</code> 将是一个长度为零的序列，
		  所以用FTL <code class="inline-code">&lt;#list ...&gt;</code> 也可以进行。</p>

          <p>知道这样一个结果是很重要的，比如，如果 <code class="inline-code">book</code> 
		  没有 <code class="inline-code">chapter</code>，那么 <code class="inline-code">book.chapter</code> 
		  就是一个空序列，所以 <code class="inline-code">doc.book.chapter??</code> 
		  就 <em>不会</em> 是 <code class="inline-code">false</code>，它就一直是 
		  <code class="inline-code">true</code>！类似地，<code class="inline-code">doc.book.somethingTotallyNonsense??</code> 
		  也不会是 <code class="inline-code">false</code>。来检查是否有子结点，可以使用 
		  <code class="inline-code">doc.book.chapter[0]??</code>(或<code class="inline-code">doc.book.chapter?size == 0</code>)。
		  当然你可以使用类似所有的<a href="dgui_template_exp.html#dgui_template_exp_missing">空值处理操作符</a>
		  (比如 <code class="inline-code">doc.book.author[0]!&quot;Anonymous&quot;</code> )，只是不要忘了那个 
		  <code class="inline-code">[0]</code>。</p>

            <div class="callout note">
    <strong class="callout-label">Note:</strong>

            <p>序列的大小是1的规则是方便XML包装的方便特性(通过多类型的FTL变量来实现)。
			通常其他序列将不会起作用。</p>
            </div>


          <p>现在我们完成了打印每个chapter所有的 <code class="inline-code">para</code> 示例：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;h1&gt;${doc.book.title}&lt;/h1&gt;
&lt;#list doc.book.chapter as ch&gt;
  &lt;h2&gt;${ch.title}&lt;/h2&gt;
  &lt;#list ch.para as p&gt;
    &lt;p&gt;${p}
  &lt;/#list&gt;
&lt;/#list&gt;</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">&lt;h1&gt;Test&lt;/h1&gt;
  &lt;h2&gt;Ch1&lt;/h2&gt;
    &lt;p&gt;p1.1
    &lt;p&gt;p1.2
    &lt;p&gt;p1.3
  &lt;h2&gt;Ch2&lt;/h2&gt;
    &lt;p&gt;p2.1
    &lt;p&gt;p2.2</pre></div>

          <p>上面的FTL可以书写的更加漂亮：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#assign book = doc.book&gt;
&lt;h1&gt;${book.title}&lt;/h1&gt;
&lt;#list book.chapter as ch&gt;
  &lt;h2&gt;${ch.title}&lt;/h2&gt;
  &lt;#list ch.para as p&gt;
    &lt;p&gt;${p}
  &lt;/#list&gt;
&lt;/#list&gt;</pre></div>

          <p>最终，一个&quot;广义的&quot;子结点选择机制是：
		  模板列出所有示例XML文档的<code class="inline-code">para</code>：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#list doc.book.chapter.para as p&gt;
  &lt;p&gt;${p}
&lt;/#list&gt;</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">  &lt;p&gt;p1.1
  &lt;p&gt;p1.2
  &lt;p&gt;p1.3
  &lt;p&gt;p2.1
  &lt;p&gt;p2.2
  </pre></div>

          <p>这个示例说明了哈希表变量选择序列子结点的做法
		  (在前面示例中的序列大小为1)。在这个具体的例子中，子变量 
		  <code class="inline-code">chapter</code> 返回一个大小为2的序列
		  (因为有两个 <code class="inline-code">chapter</code>)，之后子变量 
		  <code class="inline-code">para</code> 在那个序列中选择 <code class="inline-code">para</code> 
		  所有结点的子结点。</p>

          <p>这种机制的一个负面结果是类似于
		  <code class="inline-code">doc.somethingNonsense.otherNonsesne.totalNonsense</code> 
		  这样的东西会被算作是空序列，而且你也不会得到任何错误信息。</p>
        
          



<h2 class="content-header header-section2" id="autoid_133">访问属性</h2>


          <p>这个XML和原来的那个是相同的，除了它使用title属性，而不是元素：</p>

          

<div class="code-wrapper"><pre class="code-block code-unspecified">&lt;!-- THIS XML IS USED FOR THE &quot;Accessing attributes&quot; CHAPTER ONLY! --&gt;
&lt;!-- Outside this chapter examples use the XML from earlier.       --&gt;

&lt;book title=&quot;Test&quot;&gt;
  &lt;chapter title=&quot;Ch1&quot;&gt;
    &lt;para&gt;p1.1&lt;/para&gt;
    &lt;para&gt;p1.2&lt;/para&gt;
    &lt;para&gt;p1.3&lt;/para&gt;
  &lt;/chapter&gt;
  &lt;chapter title=&quot;Ch2&quot;&gt;
    &lt;para&gt;p2.1&lt;/para&gt;
    &lt;para&gt;p2.2&lt;/para&gt;
  &lt;/chapter&gt;
&lt;/book&gt;</pre></div>

          <p>一个元素的属性可以通过和元素的子元素一样的方式来访问，
		  除了你在属性名的前面放置一个@符号：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#assign book = doc.book&gt;
&lt;h1&gt;${book.@title}&lt;/h1&gt;
&lt;#list book.chapter as ch&gt;
  &lt;h2&gt;${ch.@title}&lt;/h2&gt;
  &lt;#list ch.para as p&gt;
    &lt;p&gt;${p}
  &lt;/#list&gt;
&lt;/#list&gt;</pre></div>

          <p>这会打印出和前面示例相同的结果。</p>

          <p>按照和获取子结点一样的逻辑来获得属性，所以上面的 
		  <code class="inline-code">ch.@title</code> 结果就是大小为1的序列。如果没有 
		  <code class="inline-code">title</code> 属性，那么结果就是一个大小为0的序列。
		  所以要注意，这里使用内建函数也是有问题的：如果你很好奇 
		  <code class="inline-code">foo</code> 是否含有属性 <code class="inline-code">bar</code>，
		  那么你不得不写 <code class="inline-code">foo.@bar[0]??</code>。
		  (<code class="inline-code">foo.@bar??</code> 是不对的，因为它总是返回 
		  <code class="inline-code">true</code>)。类似地，如果你想要一个 
		  <code class="inline-code">bar</code> 属性的默认值，那么你就不得不写 
		  <code class="inline-code">foo.@bar[0]!&quot;theDefaultValue&quot;</code>。</p>

          <p>正如子元素那样，你可以选择多结点的属性。
		  例如，这个模板将打印所有chapter的title属性：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#list doc.book.chapter.@title as t&gt;
  ${t}
&lt;/#list&gt;</pre></div>
        
          



<h2 class="content-header header-section2" id="autoid_134">探索DOM树</h2>


          <p>这个FTL将会枚举所有book元素的子结点：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#list doc.book?children as c&gt;
- ${c?node_type} &lt;#if c?node_type == &#39;element&#39;&gt;${c?node_name}&lt;/#if&gt;
&lt;/#list&gt;</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">- text
- element title
- text
- element chapter
- text
- element chapter
- text</pre></div>

          <p><code class="inline-code">?node_type</code> 的意思可能没有解释清楚。
		  有一些在DOM树中存在的结点类型，比如 <code class="inline-code">&quot;element&quot;</code>，
		  <code class="inline-code">&quot;text&quot;</code>，<code class="inline-code">&quot;comment&quot;</code>，
		  <code class="inline-code">&quot;pi&quot;</code>等。</p>

          <p><code class="inline-code">?node_name</code> 返回结点的结点名称。
		  对于其他的结点类型，也会返回一些东西，但是它对声明的XML处理更有用，这会在<a href="xgui_declarative.html">后面章节</a>中讨论。</p>

          <p>如果book元素有属性，由于实际的原因它可能 
		  <em>不会</em> 在上面的列表中出现。
		  但是你可以获得包含元素所有属性的列表，使用变量元素的子变量 
		  <code class="inline-code">@@</code>。如果你将XML的第一行修改为这样：</p>

          

<div class="code-wrapper"><pre class="code-block code-unspecified">&lt;book foo=&quot;Foo&quot; bar=&quot;Bar&quot; baaz=&quot;Baaz&quot;&gt;</pre></div>

          <p>然后运行这个FTL：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#list doc.book.@@ as attr&gt;
- ${attr?node_name} = ${attr}
&lt;/#list&gt;</pre></div>

          <p>然后得到这个输出(或者其他相似的结果)：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">- baaz = Baaz
- bar = Bar
- foo = Foo</pre></div>

          <p>要返回子结点的列表，有一个方便的子变量来仅仅列出元素的子元素：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#list doc.book.* as c&gt;
- ${c?node_name}
&lt;/#list&gt;</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">- title
- chapter
- chapter</pre></div>

          <p>你可以使用内建函数 <code class="inline-code">parent</code> 来获得元素的父结点：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#assign e = doc.book.chapter[0].para[0]&gt;
&lt;#-- Now e is the first para of the first chapter --&gt;
${e?node_name}
${e?parent?node_name}
${e?parent?parent?node_name}
${e?parent?parent?parent?node_name}</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">para
chapter
book
@document</pre></div>

          <p>在最后一行你访问到了DOM树的根结点，文档结点。
		  它不是一个元素，这就是为什么得到了一个奇怪的名字；
		  现在我们不来处理它。很明显，文档结点没有父结点。</p>

          <p>你可以使用内建函数 <code class="inline-code">root</code> 来快速返回到文档结点：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#assign e = doc.book.chapter[0].para[0]&gt;
${e?root?node_name}
${e?root.book.title}</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">@document
Test Book</pre></div>

          <p>在内建函数完整的列表中你可以用来在DOM树中导航，
		  可以阅读<a href="ref_builtins_node.html">结点内建函数参考</a>。</p>
        
          



<h2 class="content-header header-section2" id="autoid_135">使用XPath表达式</h2>


            <div class="callout note">
    <strong class="callout-label">Note:</strong>

            <p>XPath表达式仅在<a href="http://jaxen.org/">Jaxen</a>(推荐使用，
			但是使用至少Jaxen 1.1-beta-8版本，不能再老了)或<a href="http://xml.apache.org/xalan/">Apache Xalan</a>库可用时有效。
			(Apache Xalan库在Sun J2SE 1.4，1.5和1.6(也许在后续版本)中已经包含了；
			不需要独立的Xalan的jar包。)</p>
            </div>


            <div class="callout note">
    <strong class="callout-label">Note:</strong>

            <p>不要使用前一部分的示例XML，那里的<code class="inline-code">title</code> 
			是一个属性；仅对那部分使用。</p>
            </div>


          <p>如果哈希表的键使用了结点变量而不能被解释(<a href="xgui_imperative_formal.html">下一部分</a>对此精确定义)，
		  那么它就会被当作Xpath表达式被解释。要获得XPath的更多信息，
		  可以访问<a href="http://www.w3.org/TR/xpath">http://www.w3.org/TR/xpath</a>。</p>

          <p>例如，这里我们列出 <code class="inline-code">title</code> 
		  元素(不是属性！)内容为&quot;Ch1&quot;的chapter的 <code class="inline-code">para</code> 元素：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#list doc[&quot;book/chapter[title=&#39;Ch1&#39;]/para&quot;] as p&gt;
  &lt;p&gt;${p}
&lt;/#list&gt;</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">  &lt;p&gt;p1.1
  &lt;p&gt;p1.2
  &lt;p&gt;p1.3</pre></div>

          <p>长度为1(在前面部分解释过了)的序列的规则也代表XPath的结果。
		  也就是说，如果结果序列仅仅包含1个结点，它也会当作结点自身。
		  例如，打印chapter元素&quot;Ch1&quot;第一段：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">${doc[&quot;book/chapter[title=&#39;Ch1&#39;]/para[1]&quot;]}</pre></div>

          <p>这也会输出相同内容：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">${doc[&quot;book/chapter[title=&#39;Ch1&#39;]/para[1]&quot;][0]}</pre></div>

          <p>XPath表达式的内容结点(或者是结点序列)
		  是哈希表子变量被用作发布XPath表达式的结点。
		  因此，这将打印和上面例子相同的内容：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">${doc.book[&quot;chapter[title=&#39;Ch1&#39;]/para[1]&quot;]}</pre></div>

          <p>请注意，现在你可以使用0序列或多(比1多)结点作为内容，
		  这只在程序员已经建立 FreeMarker 使用Jaxen而不是Xalan时才可以。</p>

          <p>也要注意XPath序列的项索引从1开始，而FTL的序列项索引是用0开始的。
		  因此，要选择第一个chapter，XPath表达式是 <code class="inline-code">&quot;/book/chapter[1]&quot;</code>，
		  而FTL表达式是 <code class="inline-code">book.chapter[0]</code>。</p>

          <p>如果程序员设置 FreeMarker 使用Jaxen而不是Xalan，
		  那么 FreeMarker 的变量在使用XPath变量引用时是可见的：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#assign <strong>currentTitle</strong> = &quot;Ch1&quot;&gt;
&lt;#list doc[&quot;book/chapter[title=<strong>$currentTitle</strong>]/para&quot;] as p&gt;
<em>...</em></pre></div>

          <p>请注意，<code class="inline-code">$currentTitle</code> 不是 FreeMarker 的插值，
		  因为那里没有 <code class="inline-code">{</code> 和 <code class="inline-code">}</code>。
		  那是XPath表达式。</p>

          <p>一些XPath表达式的结果不是结点集，而是字符串，数字或者布尔值。
		  对于那些XPath表达式，结果分别是FTL字符串，数字或布尔值变量。
		  例如，下面的例子将会计算XML文档中 <code class="inline-code">para</code> 元素的总数，
		  所以结果是一个数字：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">${x[&quot;count(//para)&quot;]}</pre></div>

          <p>将会输出：</p>

          

<div class="code-wrapper"><pre class="code-block code-output">5</pre></div>
        
          



<h2 class="content-header header-section2" id="autoid_136">XML命名空间</h2>


          

          <p>默认来说，当你编写如 <code class="inline-code">doc.book</code> 这样的东西时，
		  那么它会选择属于任何XML命名空间(和XPath相似)名字为 
		  <code class="inline-code">book</code> 的元素。如果你想在XML命名空间中选择一个元素，
		  你必须注册一个前缀，然后使用它。比如，如果元素 <code class="inline-code">book</code> 
		  是命名空间 <code class="inline-code">http://example.com/ebook</code>，
		  那么你不得不关联一个前缀，要在模板的顶部使用 <a href="ref_directive_ftl.html#ref.directive.ftl"><code>ftl</code>
          指令</a> 的 <code class="inline-code">ns_prefixes</code> 参数：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#ftl ns_prefixes={&quot;e&quot;:&quot;http://example.com/ebook&quot;}&gt;</pre></div>

          <p>现在你可以编写如 <code class="inline-code">doc[&quot;e:book&quot;]</code> 的表达式。
		  (因为冒号会混淆 FreeMarker，方括号语法的使用是需要的。)</p>

          <p><code class="inline-code">ns_prefixes</code> 的值作为哈希表，
		  你可以注册多个前缀：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#ftl ns_prefixes={
    &quot;e&quot;:&quot;http://example.com/ebook&quot;,
    &quot;f&quot;:&quot;http://example.com/form&quot;,
    &quot;vg&quot;:&quot;http://example.com/vectorGraphics&quot;}
&gt;</pre></div>

          <p><code class="inline-code">ns_prefixes</code> 参数影响整个 <a href="dgui_misc_namespace.html">FTL 命名空间</a>。
		  这就意味着实际中，你在主页面模板中注册的前缀必须在所有的 <code class="inline-code">&lt;#include
          ...&gt;</code> 的模板中可见，而不是 <code class="inline-code">&lt;#imported
          ...&gt;</code> 的模板(经常用来引用FTL库)。从另外一种观点来说，
		  一个FTL库可以注册XML命名空间前缀来为自己使用，而前缀注册不会干扰主模板和其他库。</p>

          <p>要注意，如果一个输入模板是给定XML命名空间域中的，
		  为了方便你可以设置它为默认命名空间。这就意味着如果你不使用前缀，
		  如在 <code class="inline-code">doc.book</code> 中，那么它会选择属于默认命名空间的元素。
		  这个默认命名空间的设置使用保留前缀 <code class="inline-code">D</code>，例如：</p>

          

<div class="code-wrapper"><pre class="code-block code-template">&lt;#ftl ns_prefixes={&quot;D&quot;:&quot;http://example.com/ebook&quot;}&gt;</pre></div>

          <p>现在表达式 <code class="inline-code">doc.book</code> 选择属于XML命名空间 
		  <code class="inline-code">http://example.com/ebook</code> 的 <code class="inline-code">book</code> 元素。
		  不幸的是，XPath不支持默认命名空间。因此，在XPath表达式中，
		  没有前缀的元素名称通常选择不输入任何XML命名空间的元素。然而，
		  在默认命名空间中访问元素你可以直接使用前缀<code class="inline-code">D</code>，比如：
		  <code class="inline-code">doc[&quot;D:book/D:chapter[title=&#39;Ch1&#39;]&quot;]</code>。</p>

          <p>请注意，当你使用默认命名空间时，那么你可以使用保留前缀 
		  <code class="inline-code">N</code> 来选择不属于任意结点空间的元素。比如 
		  <code class="inline-code">doc.book[&quot;N:foo&quot;]</code>。这对XPath表达式不起作用，
		  上述的都可以写作 <code class="inline-code">doc[&quot;D:book/foo&quot;]</code>。</p>
        
          



<h2 class="content-header header-section2" id="autoid_137">不要忘了转义！</h2>


          <p>我们在所有的示例中都犯了大错。我们生成HTML格式的输出，
		  HTML格式保留如 <code class="inline-code">&lt;</code>，<code class="inline-code">&amp;</code> 
		  等的字符。所以当我们打印普通文本(比如标题和段落)时，
		  我们不得不转义它，因此，示例的正确版本是：</p>

          

<div class="code-wrapper"><pre class="code-block code-template"><strong>&lt;#escape x as x?html&gt;</strong>
&lt;#assign book = doc.book&gt;
&lt;h1&gt;${book.title}&lt;/h1&gt;
&lt;#list book.chapter as ch&gt;
  &lt;h2&gt;${ch.title}&lt;/h2&gt;
  &lt;#list ch.para as p&gt;
    &lt;p&gt;${p}
  &lt;/#list&gt;
&lt;/#list&gt;
<strong>&lt;/#escape&gt;</strong></pre></div>

          <p>所以如果book的标题是&quot;Romeo &amp; Julia&quot;，
		  那么HTML输出的结果就是正确的：</p>

          

<div class="code-wrapper"><pre class="code-block code-output"><em>...</em>
&lt;h1&gt;Romeo &amp;amp; Julia&lt;/h1&gt;
<em>...</em></pre></div>
        <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="xgui_imperative.html"><span>Previous</span></a><a class="paging-arrow next" href="xgui_imperative_formal.html"><span>Next</span></a></div></div></div></div>      </div>
    </div>
<div class="site-footer"><div class="site-width"><div class="footer-top"><div class="col-left sitemap"><div class="column"><h3 class="column-header">Overview</h3><ul><li><a href="http://freemarker.org/index.html">What is FreeMarker?</a></li><li><a href="http://freemarker.org/freemarkerdownload.html">Download</a></li><li><a href="app_versions.html">Version history</a></li><li><a href="http://freemarker.org/history.html">About us</a></li><li><a itemprop="license" href="app_license.html">License</a></li></ul></div><div class="column"><h3 class="column-header">Handy stuff</h3><ul><li><a href="http://freemarker-online.kenshoo.com/">Try template online</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions cheatsheet</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_builtins_alphaidx.html">?built_ins</a></li><li><a href="ref_specvar.html">.special_vars</a></li></ul></div><div class="column"><h3 class="column-header">Community</h3><ul><li><a href="https://github.com/nanlei/freemarker/tree/manual-zh-2.3-gae/src/manual">Chinese Manual on Github</a></li><li><a href="https://github.com/freemarker/freemarker">FreeMarker on Github</a></li><li><a href="https://twitter.com/freemarker">Follow us on Twitter</a></li><li><a href="https://sourceforge.net/p/freemarker/bugs/new/">Report a bug</a></li><li><a href="http://stackoverflow.com/questions/ask?tags=freemarker">Ask a question</a></li><li><a href="http://freemarker.org/mailing-lists.html">Mailing lists</a></li></ul></div></div><div class="col-right"><ul class="social-icons"><li><a class="github" href="https://github.com/freemarker/freemarker">Github</a></li><li><a class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a class="stack-overflow" href="http://stackoverflow.com/questions/ask?tags=freemarker">Stack Overflow</a></li></ul><a class="xxe" href="http://www.xmlmind.com/xmleditor/" rel="nofollow" title="Edited with XMLMind XML Editor"><span>Edited with XMLMind XML Editor</span></a></div></div><div class="footer-bottom"><p><span class="generated-for-product">Generated for: Freemarker 2.3.23</span><span class="last-updated"> Last generated:
<time itemprop="dateModified" datetime="2015-09-18T14:38:51Z" title="Friday, September 18, 2015 2:38:51 PM GMT">2015-09-18 14:38:51 GMT</time></span></p> <p class="copyright">
© <span itemprop="copyrightYear">1999</span>–2015
<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="http://freemarker.org">The FreeMarker Project</a>. All rights reserved. </p>
</div></div></div></body>
</html>
